/**
 * Copyright © 2018 organization baomidou
 * <pre>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * <pre/>
 */
package com.baomidou.dynamic.datasource.spring.boot.autoconfigure.druid;

import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

import java.lang.reflect.Field;
import java.util.Properties;

/**
 * Druid常用参数
 *
 * @author TaoYu
 * @since 1.2.0
 */
@Data
@Accessors(chain = true)
@NoArgsConstructor
public class DruidConfig {

    public Integer initialSize;
    public Integer maxActive;
    public Integer minIdle;
    public Long maxWait;
    public Long timeBetweenEvictionRunsMillis;
    public Long minEvictableIdleTimeMillis;
    public Long maxEvictableIdleTimeMillis;
    public String validationQuery;
    public Integer validationQueryTimeout;
    public Boolean testOnBorrow;
    public Boolean testOnReturn;
    public Boolean testWhileIdle;
    public Boolean poolPreparedStatements;
    public Integer maxOpenPreparedStatements;
    public Boolean sharePreparedStatements;
    public Boolean clearFiltersEnable;
    public Integer notFullTimeoutRetryCount;
    public Long maxWaitThreadCount;
    public Boolean failFast;
    public Integer phyTimeoutMillis;
    public Boolean initVariants;
    public Boolean initGlobalVariants;
    public Boolean useUnfairLock;
    public Integer maxPoolPreparedStatementPerConnectionSize;
    public String initConnectionSqls;
    public Boolean keepAlive;
    public Boolean asyncInit;
    public Boolean killWhenSocketReadTimeout;
    public Integer connectionErrorRetryAttempts;
    public Boolean breakAfterAcquireFailure;
    public String filters;
    public Properties connectionProperties;

    public static DruidConfig defaultConfig() {
        DruidConfig druidConfig = new DruidConfig();
        druidConfig.initialSize = 0;
        druidConfig.maxActive = 8;
        druidConfig.minIdle = 0;
        druidConfig.maxWait = -1L;
        druidConfig.timeBetweenEvictionRunsMillis = 60 * 1000L;
        druidConfig.minEvictableIdleTimeMillis = 1000L * 60L * 30L;
        druidConfig.maxEvictableIdleTimeMillis = 1000L * 60L * 60L * 7;
        druidConfig.validationQuery = "select 1";
        druidConfig.validationQueryTimeout = -1;
        druidConfig.testOnBorrow = false;
        druidConfig.testOnReturn = false;
        druidConfig.testWhileIdle = true;
        druidConfig.poolPreparedStatements = false;
        druidConfig.maxOpenPreparedStatements = -1;
        druidConfig.sharePreparedStatements = false;
        druidConfig.clearFiltersEnable = true;
        druidConfig.notFullTimeoutRetryCount = 0;
        druidConfig.maxWaitThreadCount = -1L;
        druidConfig.failFast = false;
        druidConfig.phyTimeoutMillis = -1;
        druidConfig.initVariants = false;
        druidConfig.initGlobalVariants = false;
        druidConfig.maxPoolPreparedStatementPerConnectionSize = 10;
        druidConfig.keepAlive = false;
        druidConfig.asyncInit = false;
        druidConfig.killWhenSocketReadTimeout = false;
        druidConfig.connectionErrorRetryAttempts = 1;
        druidConfig.breakAfterAcquireFailure = false;
        druidConfig.filters = "stat,wall";
        return druidConfig;
    }

    public DruidConfig copyGlobal(DruidConfig druidConfig) {
        for (Field field : DruidConfig.class.getDeclaredFields()) {
            try {
                if (field.get(this) == null) {
                    field.set(this, field.get(druidConfig));
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return this;
    }

    public Properties toProperties() {
        Properties properties = new Properties();
        for (Field field : DruidConfig.class.getDeclaredFields()) {
            try {
                Object obj = field.get(this);
                if (obj != null) {
                    properties.setProperty("druid." + field.getName(), String.valueOf(obj));
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return properties;
    }
}